package com.xxxx.yebserver.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxxx.yebserver.common.utils.JwtTokenUtils;
import com.xxxx.yebserver.constant.RedisContant;
import com.xxxx.yebserver.entity.Admin;
import com.xxxx.yebserver.entity.Role;
import com.xxxx.yebserver.exception.ExceptionEnum;
import com.xxxx.yebserver.exception.MyException;
import com.xxxx.yebserver.mapper.AdminMapper;
import com.xxxx.yebserver.pojo.MySecurityUser;
import com.xxxx.yebserver.service.AdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxx.yebserver.service.RoleService;
import com.xxxx.yebserver.vo.LoginVo;
import com.xxxx.yebserver.vo.RegistVo;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author cxq
 * @since 2021-06-15
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    JwtTokenUtils jwtTokenUtils;

    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    RoleService roleService;

    @Autowired
    PasswordEncoder passwordEncoder;

    /**
     * 根据用户名获取用户
     * @param username
     * @return
     */
    @Override
    public MySecurityUser getSecurityUserByUsername(String username) {
        Admin admin = getAdminByUsername(username);
        MySecurityUser user = new MySecurityUser();
        List<Role> roles = roleService.getRoles(admin.getAdminId());
        if(roles != null && roles.size()>0){
            List<String> collect = roles.stream().map(item -> item.getRoleName()).collect(Collectors.toList());
            user.setPremissionList(collect);
        }
        user.setAdmin(admin);
        return user;
    }

    /**
     * 根据用户名获取用户
     * @param username
     * @return
     */
    @Override
    public Admin getAdminByUsername(String username) {
        String s = redisTemplate.opsForValue().get(RedisContant.LONGIN_ADMIN_PREFIX + username);
        Admin admin = null;
        if(StringUtils.isEmpty(s)){
            admin = getOne(new QueryWrapper<Admin>().eq("username", username));
            if(admin == null) throw new RuntimeException("用户不存在！");
            redisTemplate.opsForValue().set(RedisContant.LONGIN_ADMIN_PREFIX + username,JSON.toJSONString(admin));
        }else{
            admin = JSON.parseObject(s, Admin.class);
        }
        return admin;
    }

    /**
     * 登录判断返回token
     * @param vo
     * @return
     */
    @Override
    public String getTokenByUsername(LoginVo vo) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(vo.getUsername());
        MySecurityUser securityUser = (MySecurityUser)userDetails;
        if(securityUser==null) throw new MyException(ExceptionEnum.USERNAME_OR_PASSWORD_EXCEPTION.getCode(),ExceptionEnum.USERNAME_OR_PASSWORD_EXCEPTION.getMsg());
        Admin admin = securityUser.getAdmin();
        boolean matches = passwordEncoder.matches(vo.getPassword(), admin.getPassword());
        if(!matches) throw new MyException(ExceptionEnum.USERNAME_OR_PASSWORD_EXCEPTION.getCode(),ExceptionEnum.USERNAME_OR_PASSWORD_EXCEPTION.getMsg());
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        return jwtTokenUtils.createToken(admin.getUsername());
    }

    /**
     * 添加admin
     * @param vo
     * @return
     */
    @Override
    public Boolean insertAdmin(RegistVo vo) {
        if(hasAdminByUsername(vo.getUsername())) throw new RuntimeException("用户名已存在！请更换");
        Admin admin = new Admin();
        admin.setUsername(vo.getUsername());
        admin.setPassword(passwordEncoder.encode(vo.getPassword()));
        return this.save(admin);
    }

    /**
     * 判断数据库中是否有对应的用户名
     * @param username
     * @return
     */
    @Override
    public Boolean hasAdminByUsername(String username) {
        int count = this.count(new QueryWrapper<Admin>().eq("username", username));
        return count>=1;
    }

    /**
     * 获取所有admin列表
     * @return
     */
    @Cacheable(value = "admin",key = "#root.methodName")
    @Override
    public List<Admin> getAllAdmin() {
        return list();
    }
}
